/**
 * ECP Web开发 基础服务.
 * Copyright(c) 2012-2020 YGSoft.Inc
 * author:biwei
 * date:2014-7-09
 */
define(["jquery", "bootstrap", "ecp.utils.des", "ecp.utils", "ecp.utils.i18n", "ecp.dmstate","ecp.component.loading", "stacktrace", "jstorage"], 
		function ($, bootstrap, desUtil, utils, locale, dmstate, PageLoading, st) {
	var pageloadings = [];
	var skins = ["nw","gw","gd","default","ngd"];
	//加载皮肤
	requireSkin();
	//统一错误处理，临时用
    if (window) {
        window.onerror = function (msg, url, num) {
			if(pageloadings.length > 0){
				$.each(pageloadings,function(){
					this.hide();
				})
			}
        	//异常信息
        	var EXCEPTION_TIMEOUT = "http://requirejs.org/docs/errors.html#timeout";
            var e = {message:msg,detail:locale.F0000.sUrl+":"+url+"\n"+locale.F0000.sLineNumber+":"+num};
            if(typeof(msg) === "string" && msg.indexOf(EXCEPTION_TIMEOUT)>= 0){
            	window.console.error(EXCEPTION_TIMEOUT + " : "+msg);
            }else{
            	Exception.show(e);
            }
            return false;
        }
    };
    bindCompression();
    var cfg = require.s.contexts["_"].config;
    var webAppRoot = cfg.webContextPath;
    var CommonConst = {
        REMOTE_SERVLET: webAppRoot+"/ecp/webcore/remoteService",
        TOKENID: "ecp_token",
        EMPTY_TOKEN: "Empty_Token",
        DataContextJcls: "com.ygsoft.ecp.core.framework.internal.context.EcpDataContext",
        LoginContextJcls : "com.ygsoft.ecp.core.framework.internal.context.LoginContext",
        BusinessContextJcls: "com.ygsoft.ecp.core.framework.internal.context.BusinessContext",
        DOMAINCODE: "F0000",
        ERROR_CODEPREFIX: "ERROR_CODE",
        RESULT_TYPEPREFIX: "RESULT_TYPE",
        RESULT_TYPE_TEXT: "0",
        RESULT_TYPE_JSON: "1",
        TOKEN: "ecpDataContext.tokenId"
    };
    var OLD_VALUE = "_oldValue";
    //Jquery扩展
    $.getQueryString = function (name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
        var r = location.search.substr(1).match(reg);
        if (r != null) return unescape(decodeURI(r[2]));
        return null;
    };
    /**
     * 3.0框架提供统一替换文本信息方法
     * 页面配置ng-title="key"
     */
    $.replaceI18nAttr = function(curLocal, ctrl,attrName){
    	var that = this;
        if (curLocal) {
        	if(!ctrl || (ctrl && ctrl.length ===0)) ctrl= $("body");
         	if(attrName){
         		 bindName = "ng-"+attrName;
                  var ng = [];
                  ng = ctrl.find("*["+bindName+"]");
                  $.each(ng, function (i, el) {
                 	 var localeName = el.getAttribute(bindName);
                 	 var val = _getModelValue(curLocal, localeName);
                 	 if(val){
                 		 el.setAttribute(attrName,val);
                 	 }
                  });
         	}else{
         		$.replaceI18nText(curLocal, ctrl);
         	}
         	
        }
    }
     /**
     * 组件皮肤控制
     */
    function requireSkin(url,param){
    	//增加旋转动画
		var initPl = new PageLoading();
		initPl.show();
		var _sk =param || $.cookie("_sk");
		var _url = url || "css!themes/default/skin/style-ecp.css";
		//因基础样式不包括颜色之类，所以任何皮肤都要增加style-ecp.css样式
		if($.inArray(_sk,skins) === -1){
			_sk = "default";
		}
		require([addStr(_url,("/"+_sk),_url.lastIndexOf("/"))],function(){
			 initPl.hide();
			 window.console && window.console.log("加载"+_sk+"皮肤");
		});
    }
	/**
	 *绑定压缩和解压缩事件
	 */
	function bindCompression(){
		 $(document).bind("keyup",function(e){
			var kc = e.keyCode;
			//解压缩
			if(e.ctrlKey==true && e.shiftKey==true){
				//ctrl + shift + z 增加解压缩标识
				if(kc === 90){
					$.cookie("decompression",1,{path:"/"});
					window.console.log("解压缩成功！清除浏览器缓存后，刷新生效。");
				}
				//ctrl + shift + x 清除解压缩标识
				if(kc === 88){
					$.removeCookie("decompression",{path:"/"});
					window.console.log("压缩成功！清除浏览器缓存后，刷新生效。");
				}
			}
		})
	}

   /**
    * 字符串指定位置添加字符串
    */
    function addStr(str,a,b){
    	b=isNaN(b)?str.length:b;
    	return str.slice(0,b)+a+str.slice(b);
    }
    //日志
    var LOG = {
        isInfoEnable: true,
        isDebugEnable: true,
        isWarnEnable: false,
        isErrorEnable: false,
        info: function (message) {
            window.console && console && console.info(message);
        },
        debug: function (message) {
            window.console && console && console.debug(message);
        },
        warn: function (message) {
            window.console && console && console.warn(message);
        },
        error: function (message) {
            window.console && console && console.error(message);
        }
    };
    //异常
    var Exception = {
        throwInfo: function (errorCode, message, exp) {
            throw {"type": 0, "errorCode": errorCode, "message": message, "cause": exp};
        },
        throwError: function (errorCode, message, exp) {
            throw {"type": 1, "errorCode": errorCode, "message": message, "cause": exp};
        },
        show: function (exp,caption,option) {
            MessageBox.show(exp.message,caption||locale.F0000.sExpTitle,option);
        }
    };
    var ExceptionConst = {
        PARAM_ERROR: function () {
            return {errorCode: "CC0001", message: locale.F0000.paramNumberError};
        },
        PARAM_TYPEERROR: function () {
            return {errorCode: "CC0002", message: locale.F0000.paramTypeError};
        }
    };
    //国际化
    var I18N = {
        loadLocale: function (curLocal, ctrl) {
            if (curLocal) {
                var ng = [];
                if (ctrl && ctrl.length === 1) {
                    ng = ctrl.find("*[ng-bind]");
                } else {
                    ng = $("[ng-bind]");
                }
                $.each(ng, function (i, el) {
                    var localeName = el.attributes["ng-bind"];
                    if (localeName) {
                    	var val =  ObjectUtil.get(curLocal, localeName.value);
                    	if(val!=null){                    		
                    		if ("INPUT" === el.nodeName.toUpperCase()) {
                    			el.value = val;
                    		} else {
                    			el.innerText = val;
                    		}
                    	}
                    }
                });
            }
        }
    };
    /**
     * 3.0框架提供统一替换文本信息方法
     */
    $.replaceI18nText = I18N.loadLocale;
    //缓存服务
    var CacheType = {
        Page: 0,
        Application: 1,
        Persistent: 2
    };
  
    function CacheImpl(container) {
        this.count = 0;
        this.space = 20;
        this.keys = [];
        if (!container) {
            container = this;
        }
        this.get = function (key) {
            return container[key];
        },
            this.put = function (key, value) {
                if (!container[key]) {
                    this.keys.push(key);
                }
                container[key] = value;
                this.count++;
            },
            this.remove = function (key) {
                container[key] = undefined;
                this.count--;
            },
            this.clear = function () {
                for (var name in container) {
                    delete container[name];
                }
            },
            this.size = function () {
                return this.count;
            }
    };
    var CacheManager = {
        //临时使用同一种缓存
        _pageCache: new CacheImpl(),
        _applicationCache: new CacheImpl(),
        _persistentCache: new CacheImpl(),
        getPageCache: function () {
            return this._pageCache;
        },
        getApplicationCache: function () {
            return this._applicationCache
        },
        getPersistentCache: function () {
            return this._persistentCache;
        }
    };
    //远程服务
    function _remote_success() {
        return this.status == RemoteConst.OK;
    };
    function _remote_fail() {
        return this.status == RemoteConst.FAIL;
    };
    function _getJsonResult(xhr) {
        //判断是否为异常
        if (xhr) {
            var retErrorCode = xhr.getResponseHeader(CommonConst.ERROR_CODEPREFIX);
            if (retErrorCode) {
                return {
                    errorCode: retErrorCode,
                    status: RemoteConst.FAIL,
                    data: xhr.responseText
                }
            } else {
                var resultType = xhr.getResponseHeader(CommonConst.RESULT_TYPEPREFIX);
                var result = {
                    status: RemoteConst.OK
                };
                if (CommonConst.RESULT_TYPE_JSON == resultType || (xhr.responseText != "" && xhr.responseText.indexOf("{") == 0)) {
                    result.data = $.parseJSON(xhr.responseText);
                } else {
                    result.data = xhr.responseText;
                }
                return result;
            }
        }
    }

    function remoteComplete(xhr, code, callback) {
		//防止重复刷新导致xhr取不到报undefined的问题
    	if(!xhr || !xhr.readyState){return;}
    	if(xhr.readyState < 2) {
    		Exception.show("网络异常，请检查客户端网络连接。");
    		return;
    	}
        if (code == "error") {
            throw {code: "C0003", message: xhr.responseText};
        }
        var result = _getJsonResult(xhr);
        result.isError = _remote_fail;
        result.isSuccess = _remote_success;
        callback(result, xhr);
    };
    function processSyncResult(xhr) {
        if (xhr && xhr.status == 200) {
            var tmpResult = _getJsonResult(xhr);
            tmpResult.isError = _remote_fail;
            tmpResult.isSuccess = _remote_success;
            if (tmpResult.isError()) {
                throw {message: tmpResult.data, detail: tmpResult.stackTrace, errorCode: tmpResult.errorCode};
            }
            return tmpResult.data;
        }
        ;
    };
    var RemoteConst = {
        FAIL: 0,
        OK: 1
    };
    
    /**
     * @param {Boolean} progressBar 是否显示进度条（全局），默认false不显示
     */
    function remoteService_DoGetAsync(serviceName, methodName, parameters, callBack, progressBar) {
		var me = this;
		//加载进度条
		if(callBack && progressBar === true){
			if(this.pageloading){
				this.pageloading.hide();
			}
			this.pageloading = new PageLoading();
			pageloadings.push(pageloading);
			this.pageloading.show();
		}
		
        var pValue = $.toJSON(parameters);
        var tokenId = DataContextUtil.getTokenId();
        //设置时区
        var timezone = utils.setTimeZone();
        var paramData = {"ecp_token": tokenId, name: serviceName + "." + methodName, params: pValue, "ecp_timezone": timezone};
        var signification = desUtil.signData(CommonConst.REMOTE_SERVLET, 'GET', paramData);
		var headers = window.isDebug ? {"debug": 1} : {};
		if (signification && signification["AZ"]) {
        	headers["AZ"] = signification["AZ"];
        }
        var cmSign = desUtil.getCmSign();
        if (cmSign) {
        	headers["CM"] = cmSign;
        }
        if (signification && signification.encryptedParam) {
        	paramData = signification.encryptedParam;
        	for (var i in paramData) {
            	if (paramData[i]) {
            		paramData[i] = encodeURIComponent(paramData[i]);
            	}
        	}
		}
        var data = {
            url: CommonConst.REMOTE_SERVLET,
            type: "GET",
            headers: headers,
            contentType: "application/x-www-form-urlencoded;charset=UTF-8",
            data: paramData
        };
        if (callBack) {
            data.complete = function (xhr, code) {
            	if(progressBar === true && me.pageloading){
            		me.pageloading.hide();
            	}
                remoteComplete(xhr, code, callBack);
            };
        } else {
            data.async = false;
        }
        return $.ajax(data);
    }
    /**
     * @param {Boolean} progressBar 是否显示进度条（全局），默认false不显示
     */
    function remoteService_DoPostAsync(serviceName, methodName, parameters, callBack, progressBar) {

        if (arguments.length < 4) {
            throw ExceptionConst.PARAM_ERROR();
        }
        if (parameters && !(parameters instanceof Array)) {
          	if($.isPlainObject(parameters)){
          		if(methodName.indexOf("(")==-1||methodName.lastIndexOf(")")==-1){
          			throw ExceptionConst.PARAM_TYPEERROR();	
        		}
        	}else{
        		throw ExceptionConst.PARAM_TYPEERROR();
            }  
        }
		var me = this;
		//加载进度条
		if(callBack && progressBar === true){
			if(this.pageloading){
				this.pageloading.hide();
			}
			this.pageloading = new PageLoading();
			pageloadings.push(pageloading);
			this.pageloading.show();
		}
        //设置时区
        var timezone = utils.setTimeZone();
        var pValue = $.toJSON(parameters);
        var tokenId = DataContextUtil.getTokenId();
        var paramData = {"ecp_token": tokenId, name: serviceName + "." + methodName, params: pValue, "ecp_timezone": timezone};
        var signification = desUtil.signData(CommonConst.REMOTE_SERVLET, 'POST', paramData);
		var headers = window.isDebug ? {"debug": 1} : {};
		if (signification && signification["AZ"]) {
        	headers["AZ"] = signification["AZ"];
        }
        var cmSign = desUtil.getCmSign();
        if (cmSign) {
        	headers["CM"] = cmSign;
        }
        if (signification && signification.encryptedParam) {
        	paramData = signification.encryptedParam;
		}
        var urlParam = "?ecp_token="+encodeURIComponent(paramData.ecp_token)+"&name="+encodeURIComponent(paramData.name);        
        var data = {
            url: CommonConst.REMOTE_SERVLET + urlParam,
            type: "POST",
            headers: headers,
            contentType: "application/x-www-form-urlencoded;charset=UTF-8",
            data: paramData
        };
        if (callBack) {
            data.complete = function (xhr, code) {
            	if(progressBar === true && me.pageloading){
            		me.pageloading.hide();
            	}
                remoteComplete(xhr, code, callBack);
            };
        } else {
            data.async = false;
        }
        return $.ajax(data);
    }
    var Remote = function (serviceName) {
        this.serviceName = serviceName;
        this.doGetAsync = function (methodName, parameters, callBack, progressBar) {
            if (arguments.length < 3) {
                throw ExceptionConst.PARAM_ERROR();
            }
            if (parameters && !(parameters instanceof Array)) {
              	if($.isPlainObject(parameters)){
              		if(methodName.indexOf("(")==-1||methodName.lastIndexOf(")")==-1){
              			throw ExceptionConst.PARAM_TYPEERROR();	
            		}
            	}else{            		
            		throw ExceptionConst.PARAM_TYPEERROR();
                }              	
            }
            return remoteService_DoGetAsync(serviceName, methodName, parameters, callBack, progressBar);
        }
        this.doGet = function (methodName, parameters) {
            if (arguments.length != 2) {
                throw ExceptionConst.PARAM_ERROR();
            }
            return processSyncResult(remoteService_DoGetAsync(serviceName, methodName, parameters));
        }
        this.doPostAsync = function (methodName, parameters, callBack, progressBar) {
            if (arguments.length < 3) {
                throw ExceptionConst.PARAM_ERROR();
            }
            return remoteService_DoPostAsync(serviceName, methodName, parameters, callBack, progressBar);
        }
        this.doPost = function (methodName, parameters) {
            if (arguments.length != 2) {
                throw ExceptionConst.PARAM_ERROR();
            }
            return processSyncResult(remoteService_DoPostAsync(serviceName, methodName, parameters, undefined));
        }
    }
    var RemoteService = {
        doGetAsync: function (serviceName, methodName, parameters, callBack) {
            var remote = new Remote(serviceName);
            return remote.doGetAsync(methodName, parameters, callBack);
        },
        doGet: function (serviceName, methodName, parameters) {
            var remote = new Remote(serviceName);
            return remote.doGet(methodName, parameters);
        },
        doPostAsync: function (serviceName, methodName, parameters, callBack) {
            var remote = new Remote(serviceName);
            return remote.doPostAsync(methodName, parameters, callBack);
        },
        doPost: function (serviceName, methodName, parameters) {
            var remote = new Remote(serviceName);
            return remote.doPost(methodName, parameters);
        }
    };
    
    function processHttpSyncResult(xhr) {
        if (xhr && xhr.status == 200) {
            var tmpResult = xhr.responseText;
            return tmpResult;
        } else {
            throw {message: xhr.responseText, detail: xhr.responseText, errorCode: "http" + xhr.status};
        }
    };

    var Http = {
        doGetAsync: function (url, parameters, callBack, addHeaders) {
            var tokenId = DataContextUtil.getTokenId();
            var postData = null;
            if (arguments.length > 2) {
                var postData = parameters;
            } else if (arguments.length == 2) {
                if ($.isFunction(parameters)) {
                    callBack = parameters;
                    parameters = null;
                    postData = parameters;
                }
            }
            ;
            if (window.isDebug) {
                if (addHeaders) {
                    addHeaders["debug"] = true;
                } else {
                    addHeaders = {"debug": true};
                }
            }
            ;
            var data = {
                url: url,
                type: "GET",
                headers: addHeaders,
                contentType: "application/x-www-form-urlencoded;charset=UTF-8",
                data: postData
            };
            if (callBack) {
                data.complete = function (xhr, code) {
                    callBack(xhr, code);
                };
            } else {
                data.async = false;
            }
            //设置时区
            utils.setTimeZone();
            return $.ajax(data);
        },
        doGet: function (url, parameters) {
            return processHttpSyncResult(this.doGetAsync(url, parameters, null));
        },
        refresh: function (url) {
            var addHeaders = {
                'If-Modified-Since': 'Thu, 25 Dec 1970 03:23:08 GMT',
                'If-None-Match': 'W/"1970-1419477788481"'
            };
            return this.doGetAsync(url, {}, null, addHeaders);
        },
        doGetAsyncWithToken: function (url, parameters, callBack) {
            if (parameters) {
                parameters["ecp_token"] = tokenId;
            } else {
                parameters = {"ecp_token": tokenId};
            }
            ;
            return this.doGetAsync(url, parameters, callBack);
        },
        doGetWithToken: function (url, parameters) {
            if (parameters) {
                parameters["ecp_token"] = tokenId;
            } else {
                parameters = {"ecp_token": tokenId};
            }
            ;
            return processHttpSyncResult(this.doGetAsync(url, parameters, null));
        },
        doPostAsync: function (url, parameters, callBack) {
            var tokenId = DataContextUtil.getTokenId();
            var postData = null;
            if (arguments.length > 2) {
                var postData = parameters;
            } else if (arguments.length == 2) {
                if ($.isFunction(parameters)) {
                    callBack = parameters;
                    parameters = null;
                    postData = parameters;
                }
            }
            ;
            if (postData) {
                postData["ecp_token"] = tokenId;
            } else {
                postData = {"ecp_token": tokenId};
            }
            ;
            var data = {
                url: url,
                type: "POST",
                headers: window.isDebug ? {
                    "debug": 1
                } : {},
                contentType: "application/x-www-form-urlencoded;charset=UTF-8",
                data: postData
            };
            if (callBack) {
                data.complete = function (xhr, code) {
                    callBack(xhr, code);
                };
            } else {
                data.async = false;
            }
            //设置时区
            utils.setTimeZone();
            return $.ajax(data);
        },
        doPost: function (url, parameters) {
            return processHttpSyncResult(this.doPostAsync(url, parameters, null));
        }
    };

    //消息框
    var MessageBox = {
        show: function (message, caption, option) {
            if ($.bsDialog) {
                $.bsDialog({title: caption, content: message});
            } else {
                alert(message);
            }
        }
    };

    //上下文管理
    var DataContextUtil = {
        ecpDataContext: null,
        webParam: null,
        currentToken: null,
        /**
         * 初始化.
         */
        init: function () {
            if (this.webParam == null) {
                this.requestDataContext();
            }
        },
        /**
         * 请求上下文.
         */
        requestDataContext: function () {
            var token = $.cookie(CommonConst.TOKEN);
            this.currentToken = token;
            var urlToken = $.getQueryString(CommonConst.TOKENID);
            if (!urlToken) {
                urlToken = $.getQueryString(CommonConst.TOKEN);
				if(!urlToken){
					//从url中获取tokenid
					urlToken = utils.getArguments(desUtil.decodeSearch(window.location.href),"tokenid");
				}
            }
            if (token == null && urlToken) {
                this.currentToken = token = urlToken;
                document.cookie = CommonConst.TOKEN + "=" + token + ";path=/";
            }
			//令牌为空直接退出
			if(!token){
				window.console && window.console.error(locale.F0000.nullToken);
				return;
			}
            this.webParam = RemoteService.doGet("com.ygsoft.ecp.component.portal.service.context.IBsPortalWebParamContext", "initWebParam", [token]);
            //websphere服务器doGet走浏览器缓存获取不到上下文，需要重新doPost请求获取。modi by zxw
            if(!this.webParam){
            	this.webParam = RemoteService.doPost("com.ygsoft.ecp.component.portal.service.context.IBsPortalWebParamContext", "initWebParam", [token]);
            }
            this.ecpDataContext = this.webParam && this.webParam.ecpDataContext;
        },
        /**
         * 判断是否初始化上下文.
         */
        isInit: function () {
        	this.init();
            return this.ecpDataContext && this.ecpDataContext.loginContext;
        },
        /**
         * 获取上下文用户ID.
         *
         * @return {number}
         */
        getUserId: function () {
            return this.getLoginContext() && this.getLoginContext().getUserId();
        },
        /**
         * 获取登录名.
         *
         * @return {string}
         */
        getUserName: function () {
            return this.getLoginContext() && this.getLoginContext().getUserName();
        },
        /**
         * 获取用户显示名.
         *
         * @return {string}
         */
        getUserDisplayName: function () {
            return this.getLoginContext() && this.getLoginContext().getUserDisplayName();
        },
        /**
         * 获取登录单位ID.
         *
         * @return {string}
         */
        getLoginOrgId: function () {
            return this.getLoginContext() && this.getLoginContext().getLoginOrgId();
        },
        /**
         * 获取登录单位名称.
         *
         * @return {string}
         */
        getLoginOrgName: function () {
            return this.getLoginContext() && this.getLoginContext().getLoginOrgName();
        },
        /**
         * 获取客户端IP.
         *
         * @return {string}
         */
        getIp: function () {
            return this.getLoginContext() && this.getLoginContext().getIp();
        },
        /**
         * 获取所访问服务的端口.
         *
         * @return {string}
         */
        getPort: function () {
            return document.location.port;
        },
        /**
         * 获取登录时间.
         *
         * @return {object} EcpDate对象
         */
        getLoginDate: function () {
            return this.getLoginContext() && this.getLoginContext().getLoginDate();
        },
        /**
         * 获取ECP上下文JSON(去掉了登陆上下文，只保留业务上下文).
         *
         * @return {string}
         */
        getEcpDataContextJson: function () {
            var ret = {};
            if (ret != null && this.ecpDataContext != null) {
                ret.jcls = CommonConst.DataContextJcls;
                ret.businessContext = this.getEcpDataContext().businessContext;
                return $.toJSON(ret);
            } else {
                var ret = {};
                ret.loginContext = {};
                ret.loginContext.jcls = CommonConst.LoginContextJcls;
                ret.loginContext.tokenId = $.cookie(CommonConst.TOKEN);
                ret.jcls = CommonConst.DataContextJcls;
                return $.toJSON(ret);
            }
        },
        /**
         * 获取空上下文JSON，在不需要业务上下文的时候使用(减少参数长度).
         * @return {string}
         */
        getEmptyEcpDataContextJson: function () {
            var ret = {};
            ret.loginContext = {};
            ret.loginContext.tokenId = $.cookie(CommonConst.TOKEN);
            ret.jcls = CommonConst.DataContextJcls;;
            return $.toJSON(ret);
        },
        getEcpDataContext: function () {
            var init = this.isInit();
            if (!init) {
                this.requestDataContext();
            }
            if(!this.ecpDataContext){
            	return this.ecpDataContext;
            }
            var ecpLoginContext = this.ecpDataContext.loginContext;
            var businessContext = this.ecpDataContext.businessContext;
            if(ecpLoginContext&&businessContext){
	            ecpLoginContext.userId && (businessContext.userId = ecpLoginContext.userId);
	            ecpLoginContext.userName && (businessContext.userName = ecpLoginContext.userName);
	            ecpLoginContext.userDisplayName && (businessContext.userDisplayName = ecpLoginContext.userDisplayName);
	            ecpLoginContext.loginOrgId && (businessContext.orgId = ecpLoginContext.loginOrgId);
	            ecpLoginContext.loginOrgName && (businessContext.orgName = ecpLoginContext.loginOrgName);
	            ecpLoginContext.loginDate && (businessContext.businessDate = ecpLoginContext.loginDate);
	            businessContext.businessDomain = "";	
            }
            return this.ecpDataContext;
        },
        /**
         * 获取登录上下文对象.
         * @return {object}
         */
        getLoginContext : function() {
        	var init = this.isInit();
			if (!init) {
				this.requestDataContext();
			}
			var loginContext = this.ecpDataContext ? this.ecpDataContext.loginContext : {};
			return {
				getUserId: function() {
					return loginContext.userId;
				},
				getUserName: function() {
					return loginContext.userName;
				},
				getUserDisplayName: function(){
					return loginContext.userDisplayName;
				},
				getLoginOrgId: function() {
					return loginContext.loginOrgId;
				},
				getLoginOrgName: function() {
					return loginContext.loginOrgName;
				},
				getIp: function () {
		            return loginContext.ip || null;
		        },
		        getLoginDate: function () {
		            return loginContext.loginDate;
		        }
			};
        },
        /**
		 * 获取业务上下文对象.
		 * 
		 * @return {object}
		 */
        getBusinessContext : function(){
        	return this.getEcpDataContext().businessContext;
        },
        /**
         * 获取顶层单位ID.
         *
         * @return {string}
         */
        getCompidTop: function () {
            return this.isInit() && this.webParam && this.webParam.compidTop;
        },
        /**
         * 获取当前登录单位DCCODE.
         *
         * @return {string}
         */
        getDccode: function () {
            return this.isInit() && this.webParam && this.webParam.dccode;
        },
        /**
         * 获取当前登录单位数据中心层级.
         *
         * @return {string}
         */
        getDataCenterLevel: function () {
            return this.isInit() && this.webParam && this.webParam.dataCenterLevel;
        },
        /**
         * 获取共享库单位代码(有MAIN时返回MAIN，无MAIN返回具体COMPID).
         *
         * @return {string}
         */
        getShareCompCode: function () {
            return this.isInit() && this.webParam && this.webParam.shareCompCode;
        },
        /**
         * 获取用户角色ID
         * @return {int}
         */
        getRoleId: function () {
            return this.isInit() && this.webParam && this.webParam.authCode || 4;
        },
        /**
         * 获取当前用户VO
         * @return com.ygsoft.ecp.app.mdm.service.xtyhxx.EcpUserInfoVO
         */
        getUserVO: function () {
            return this.isInit() && this.webParam && this.webParam.curUser;
        },
        /**
		 * 获取上次登录成功的时间.
		 * @return java.util.date;
		 */
		getLastLoginTime : function() {
			return this.webParam && this.webParam.lastLoginTime;
		},
		/**
		 * 获取上次登录时间描述.
		 * @return string
		 */
		getLastLoginDesc : function() {
			var last = this.getLastLoginTime();
			var ld = this.getLoginDate();
			var ret;
			if (last && ld) {
				var log = new Date(ld.year + "/" + ld.month + "/" + ld.day + " " + ld.hour + ":" + ld.minute + ":" + ld.second);
				var reg = /\d+/;
				var t = last.match(reg)[0];
				var step = Math.abs((log - t)/1000);// 换算秒
				if (step <60) {
					ret = step + "秒前";
				} else if (step < 3600) {
					ret = parseInt(step/60, 10) + "分钟前";
				} else if (step < 86400) {
					ret = parseInt(step/3600, 10) + "小时前";
				} else {
					ret = parseInt(step/86400, 10) + "天前";
				}
			}
			return ret;
		},
		getAreaBz : function() {
			return this.isInit() && this.webParam && this.webParam.areaBz;
		},
        newEcpDataContext: function () {
            return {jcls: CommonConst.DataContextJcls};
        },
        createLoginContext: function () {
            return {};
        },
        createBusinessContext: function () {
            return {jcls: CommonConst.BusinessContextJcls};
        },
        getTokenId: function () {
            var tokenId = $.getQueryString(CommonConst.TOKENID);
            if (!tokenId) {
                var tokenId = $.getQueryString(CommonConst.TOKEN);
                if (!tokenId) {
                    tokenId = $.cookie(CommonConst.TOKENID);
                    if (!tokenId) {
                        tokenId = $.cookie(CommonConst.TOKEN);
                    }
                }
            }
            if (!tokenId) {
                tokenId = CommonConst.EMPTY_TOKEN;
            }
            return tokenId;
        }
    };
//工具类
//字符串
//数组
//数据处理
    function _getModelValue(model, path) {
    	if(!model || !path){
    		return "";
    	}
        var exists = path in model;
        if (exists) {
            return model[path];
        } else {
            var props = path.split(".");
			var props0 = props[0];
			if(typeof(props0) === "string" && props0.indexOf("[")>=0){
				props0 = props0.substring(0,props0.indexOf("["));
			}
            var exists = props0 in model;
            var i = 0;
            //兼容key中增加了主key
            if (exists==false) {
                i=1;
            }
            var value;
            if(props.length>i){
            	 var len = props.length;
                 var deep = true;
                 do {
					 var propStr = props[i];
					 if( typeof(propStr) === "string" && propStr.indexOf("[") >=0 ){
						value = eval("model."+propStr);
					 }else{
						value = model[props[i]];
					 }
                     
                     if (value) {
                         i++;
                         model = value;
                     } else {
                         deep = false;
                     }
                 } while (i < len && deep)
            }
            return value;
        }
    };
    window.__dmstate = dmstate;
    /**
     * 修改模型状态，设置_oldValue
     */
    function _modifyModelState(model, path, oldValue, orgModel){
    	if(!model){return;}
    	if(!model[OLD_VALUE]){
    		model[OLD_VALUE] = {};
    	}
    	var dmState = window.__dmstate;
    	model[OLD_VALUE][path] = oldValue;
    	//设置状态
    	var ms = model.modelState;
    	if(!ms){
    		ms = model.modelState = dmState.DEFAULT;
    	}
    	//当前状态不是修改状态或删除或新增状态就修改成修改状态
    	if(dmState && !dmState.isModify(ms) && !dmState.isDelete(ms) && !dmState.isNew(ms)){
    		if(dmState.isDefault(ms)){
    			ms = dmState.MODIFY;
    		}else{
    			ms ^= dmState.MODIFY;
    		}
    		model.modelState = ms;
    		//大模型状态修改
    		if(orgModel){
    			var orgms = orgModel.modelState;
    			if(orgms){
    				if(dmState.isDefault(orgms)){
    					orgms = dmState.MODIFY;
    				}else if(!dmState.isModify(orgms)){
    					orgms ^= dmState.MODIFY;
    				}
    				orgModel.modelState = orgms;
    			}else{
    				orgModel.modelState = dmState.MODIFY;
    			}
    		}
    	}
    }
    
    /**
     * @param model 大模型
     * @param path 路径
     * @param value 新值
     * @param oldValue 旧值，当isGrid为true时表示删除的旧值（deletedList）
     * @param isGrid 是否为表格（qzzgrid）
     */
    function _setModelValue(model, path, value, oldValue, isGrid) {
    	if(oldValue === undefined){
    		oldValue = _getModelValue(model, path);
    	}
        var exists = path in model;
        if (exists || path.indexOf(".") === -1) {
            model[path] = value;
            //设置oldValue
            if(!isGrid && value !== oldValue){
            	_modifyModelState(model, path, oldValue);
            }
        } else {
            var props = path.split("."),
            	i = 0, obj,childGrid=false,
            	len = props.length,
            	orgModel = model;
            do {
				var propStr = props[i];
				if( typeof(propStr) === "string" && propStr.indexOf("[") >=0 ){
					obj = eval("model."+propStr);
					childGrid = true;
				}else{
					obj = model[props[i]];
				}
                if (value !== undefined) {
                    i++;
                    model = obj;
                } else {
					if(childGrid){
						eval("model."+props[i]+"={}");
						model = eval("model."+props[i]);
					}else{
						model[props[i]] = {};
						model = model[props[i]];
					}
                    obj = model;
                    i++;
                }
            } while (i < (len - 1)){
            	//倒数第二个，最后一个是属性
            	if(isGrid){
            		obj[0][props[i]] = value;
            	}else{
					if(childGrid){
						eval("obj."+props[i]+" = value");
					}else{
						obj[props[i]] = value;
					}
            	}
            	//设置oldValue
                if(!isGrid && value !== oldValue){
                	_modifyModelState(obj, props[i], oldValue, orgModel);
                }
            }
        }
        //处理表格的deletedList.
        if(isGrid === true && oldValue && oldValue.length !==0){
        	if(!model[OLD_VALUE]){
        		model[OLD_VALUE] = {};
        	}
       	 	model[OLD_VALUE][path+".deletedList"] = oldValue;
        }
    };
    //对象操作工具类
    var ObjectUtil = {
        get: _getModelValue,
        set: _setModelValue
    }

    //阻塞调用工具类
    function doExecute(isAbort) {
        this.isSuspend = false;
        this.isExecuted = true;
        //只有中间节点才有abortcallBack
        var abortReturn = this.abortCallBack && this.abortCallBack.call(null, this.priorNode.returnValue);
        if (isAbort || abortReturn) {
            this.returnValue = false;
            return false;
        } else {
            //不是最后一个回调时，复制参数,能直接改参数
            if (!this.isLast) {
                var p = [];
                if (this.parameters) {
                    for (var i = 0; i < this.parameters.length; i++)
                        p.push(this.parameters[i]);
                }
                ;
                if (this.nextNode) {
                    p.push(this.nextNode);
                }
                ;
                if (this.executor) {
                    //如果传进来的是个对象，则判断是否实现了指定的接口方法
                    if (this.executor.execute) {
                        this.returnValue = this.executor.execute.apply(this.executor, p);
                    } else {
                        this.returnValue = this.executor.apply(null, p);
                    }
                }
                ;
            } else {
                //最后一个节点时取以前节点的返回值
                var retValues = [];
                var pNode = this.priorNode;
                while (pNode) {
                    retValues.push(pNode.returnValue);
                    pNode = pNode.priorNode;
                }
                ;
                retValues.reverse();
                //只有一个结果时不用数组
                if (retValues.length == 1) {
                    retValues = retValues[0];
                }
                ;
                //最后一个要用Call，把返回结果当作一个数组传递
                if (this.executor) {
                    if (this.executor.execute) {
                        this.returnValue = this.executor.execute.call(this.executor, retValues);
                    } else {
                        this.returnValue = this.executor.call(null, retValues);
                    }
                }
                ;
            }
            ;
            //下一节点存在并且没有执行且是非暂停模式下需要手动调用,这样就避免了每个执行者都要写回调
            //只需要有界面交互的需要设置suspend,如果执行器写了回调也没有问题，不会重复执行
            var nextNode = this.nextNode;
            if (nextNode && !nextNode.isExecuted && !nextNode.isSuspend) {
                this.nextNode.execute(false);
            }
            ;
            return this.returnValue;
        }
        ;
    };
    function doSuspend() {
        this.isSuspend = true;
    };
    function ExecuteNode(executor, parameters, abortCallBack) {
        this.executor = executor;
        this.nextNode = null;
        this.execute = doExecute;
        this.suspend = doSuspend;
        this.parameters = parameters;
        this.returnValue = null;
        this.isLast = false;
        this.priorNode = null;
        this.isSuspend = false;
        this.isExecuted = false;
        this.abortCallBack = abortCallBack;
    };
    function blockExecute(executors, parameters, callback, abortCallBack) {
        if (executors) {
            var firstNode, nextNode;
            //只有中间节点才需要设置中断回调
            var lastExecuteNode = new ExecuteNode(callback, parameters);
            lastExecuteNode.isLast = true;
            if ($.isArray(executors)) {
                for (var index = 0; index < executors.length; index++) {
                    if (nextNode) {
                        nextNode.nextNode = new ExecuteNode(executors[index], parameters, abortCallBack);
                        nextNode.nextNode.priorNode = nextNode;
                        nextNode = nextNode.nextNode;
                    } else {
                        firstNode = new ExecuteNode(executors[index], parameters);
                        nextNode = firstNode;
                    }
                    ;
                }
                ;
                if (nextNode) {
                    nextNode.nextNode = lastExecuteNode;
                    nextNode.nextNode.priorNode = nextNode;
                }
                ;
            } else if (executors) {
                firstNode = new ExecuteNode(executors, parameters);
                firstNode.nextNode = lastExecuteNode;
                firstNode.nextNode.priorNode = firstNode;
            }
            ;
            //数组为空或传个null
            if (!firstNode) {
                firstNode = lastExecuteNode;
            }
            ;
            var firstResult = firstNode.execute(false);
            var resultNode = lastExecuteNode;
            var returnValue = null;
            while (resultNode) {
                if (resultNode.isExecuted) {
                    returnValue = resultNode.returnValue;
                    break;
                }
                resultNode = resultNode.priorNode;
            }
            return returnValue;
        } else {
            if (callback) {
                return callback();
            } else {
                //什么都没执行
                return false;
            }
        }
    };
    var BlockUtil = {
        blockExecute: blockExecute
    };

    var config_define = {
        getRequireConfig: function () {
            return cfg;
        },
        changeTheme: function (newTheme) {
            //同步调用
            Http.doPost(webAppRoot + "/ecp/webcore/changeServlet", { "ecp_theme": newTheme });
            var maincss = $("#maincss");
            //设置Cookie
            $.cookie("ecp_theme", newTheme);
            if (maincss && maincss.length === 1) {
            	var href = maincss.attr("href");
            	maincss.attr("href", href + "?v=" + Math.random());
            }
        },
        getTheme: function () {
            return $.cookie("ecp_theme");
        },
        changeLocale: function (newLocale) {
            //同步调用
            Http.doPost(webAppRoot+"/ecp/webcore/changeServlet", {"ecp_locale": newLocale});
            //设置Cookie
            $.cookie("ecp_locale", newLocale);
        },
        getLocale: function () {
            return $.cookie("ecp_locale");
        },
        refreshPage: function () {
            Http.refresh(webAppRoot+"/ecp/webcore/themes/style.css");
            Http.refresh(webAppRoot+"/ecp/webcore/scripts/ecp.starter.js");
            var url = document.location.href;
            var index = url.indexOf("?");
            if (index > 0) {
                var pos = url.indexOf('_v');
                if (pos > 0) {
                    url = url.substring(0, pos);
                }
                url = url + "_v=" + Math.random();
            } else {
                url = url + "?_v=" + Math.random();
            }
            document.location.href = url;
        },
        localeUrlEncode: function (url) {
            return url;
        }
    };

    var angular_define = {
        bootstrap: function (element, modules) {
            var doBootstrap = function () {
                element = jQuery(element);
                modules = modules || [];
                modules.unshift(['$provide', function ($provide) {
                    $provide.value('$rootElement', element);
                }]);
                modules.unshift('ng');
                var injector = angular.injector(modules);
                injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
                        function (scope, element, compile, injector, animate) {
                            scope.$apply(function () {
                                element.data('$injector', injector);
                                compile(element)(scope);
                            });
                        }]
                );
                return injector;
            };
            var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/;
            if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) {
                return doBootstrap();
            }
            window.name = window.name.replace(NG_DEFER_BOOTSTRAP, '');
            angular.resumeBootstrap = function (extraModules) {
                forEach(extraModules, function (module) {
                    modules.push(module);
                });
                doBootstrap();
            };
        }
    };

    var service = {
        Log: LOG,
        Exception: Exception,
        Remote:Remote,
        RemoteService:RemoteService,
        RemoteConst: RemoteConst,
        MessageBox: MessageBox,
        Locale: locale,
        I18N: I18N,
        CacheManager: CacheManager,
        Http: Http,
        ObjectUtil:ObjectUtil,
        DataContextUtil: DataContextUtil,
        BlockUtil: BlockUtil,
        ConfigUtil: config_define,
        requireSkin:requireSkin,
        AngularUtil: angular_define
    };
    if (LOG.isInfoEnable) {
        LOG.info("ecp.service started succeed.");
    }
    //加载机器人
    if($.jStorage && $.jStorage.get("ecpRobotCs")){
    	require(["/grm/intelligence/EcpRobotJs/ecp.web.robot3.0.js"],function(robot){robot.render(null,service);});
    }
    return service;
})
